iT邦幫忙

2024 iThome 鐵人賽

DAY 9
0

程式接縫 Seam

簡介

  • 定義: 程式碼裡面特殊的一個點, 在這些點上不需做任何更改即可達到改變程式行為的目的
  • 如何讓一個程式碼做改變呢?
    • 假設原有個function, 新增 virtual修飾詞, 並將實作複製到別的class且同一個signature的static function

我們以一個Student範例, 計算成績Score時有個CalculateScore()函數

重構前範例

public class Student
{
    public Score CalculateScore()
	{
		 Console.WriteLine("Calculate score");
		 TransferCourseDetail(CourseTypes.Major);
         // next calculation flow
	}

	public void TransferCourseDetail(CourseTypes types)
	{
		 //....
	}
}

重構後範例

public class Student
{
    public Score CalculateScore()
	{
		 Console.WriteLine("Calculate score");
		 TransferCourseDetail(CourseTypes.Major);
         // next calculation flow
	}

	public virtual void TransferCourseDetail(CourseTypes types)
	{
		 CourseDetail.TransferDetail(types);
	}
	
	
}

public class CourseDetail
{
    public static void TransferDetail(CourseTypes types)
	{
		 //....
	}
}

從上面看到, 我們為TransferCourseDetail函數新增virtual修飾詞, 並將實作的邏輯,
移動到新的CourseDetail類別的TransferDetail函數.
因此, virtual void TransferCourseDetail成為一個Seam.

Seam能幫我們什麼?

如果今天要維護一個沒有測試的程式碼, 或者要重構, 此時為了要確保程式邏輯能被驗證,
讓seam可以做替換功能, 驗證我們想先關注的部分.

回到上面的例子, 如果CalculateScore只是想先確認回傳的Score物件是符合"初步"預期,
TransferDetail的實作可以先忽略, 那麼寫單元測試時, TransferDetail可以被override為空實作或者簡單的assertion.

另外CourseDetail也抽出獨立的TransferDetail函數, 也能單獨測試它的功能.

最終兩邊class的TransferDetail測試都完成, 後續再考慮使用哪些重構做改善.

Seam的其他用法

  • 以C/C++的實作, 能用#ifdef來引入自定義的marco, 可替代既有的function作為seam
  • 替換dll也是一種Seam點

上一篇
Replace Constructor with Creation Method 的重構
下一篇
新生(Sprout) 方法與類別
系列文
程式淨化計畫:痛苦是重構的起源!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言